#include "RF24L01.h"

// 寄存器初始化配置
const unsigned char InitAddr[3][6] =
{
    { RX_ADDR_P0,    INIT_ADDR_PIPE0 },
    { RX_ADDR_P1,    INIT_ADDR_PIPE1 },
    { TX_ADDR,       INIT_ADDR_TXADDR }
};
const unsigned char InitRegMap[25][2] =
{
    //中断线设置 CRC 电源 RX或TX模式
    { CONFIG,       EN_CRC | CRC_1BYTE },

    //自动应答哪些通道
    { EN_AA,        ENAA_P0 | ENAA_P1 | ENAA_P2 | ENAA_P3 | ENAA_P4 | ENAA_P5 },

    //接收哪些通道数据
    { EN_RXADDR,    ERX_P0 },

    //地址宽度
    { SETUP_AW,     AW_3BYTES },

    //自动应答延时时长, 次数
    { SETUP_RETR,   ARD_250US( WAIT_TIME_X_250US ) | ARC_DISABLE /*ARC_1TIMES( RETRY_TIMES )*/ },

    //频点设置
    { RF_CH,        0x02 },

    //连续发射 空中波特率 功率
    { RF_SETUP,     RF_DR_LOW_250K | PWR_0DB },

    //清空中断标志
    { STATUS,       RX_DR | TX_DS | MAX_RT },

    //各地址, 有几个地址是5字节的,另外设置
    { RX_ADDR_P2,   INIT_ADDR_PIPE2 },
    { RX_ADDR_P3,   INIT_ADDR_PIPE2 },
    { RX_ADDR_P4,   INIT_ADDR_PIPE2 },
    { RX_ADDR_P5,   INIT_ADDR_PIPE2 },

    //各通道数据长度,或最大长度
    { RX_PW_P0,     PIPE0_PACKET_LEN },
    { RX_PW_P1,     PIPE1_PACKET_LEN },
    { RX_PW_P2,     PIPE2_PACKET_LEN },
    { RX_PW_P3,     PIPE3_PACKET_LEN },
    { RX_PW_P4,     PIPE4_PACKET_LEN },
    { RX_PW_P5,     PIPE5_PACKET_LEN },

    //各通道动态数据包的开关
    { DYNPD,        DPL_P0 | DPL_P1 | DPL_P2 | DPL_P3 | DPL_P4 | DPL_P5 },

    //动态数据包 ACK载荷 动态选择NoACK 的开关
    { FEATRUE,      EN_DPL | EN_DYN_ACK },

    //初始化结束标志,循环到此就不写入寄存器了
    { 0xFF,         0xFF}
};

//触发发送,CE保持10us
void NRF24L01_Trig_Tx( void )
{
    RF24L01_SET_CE_HIGH;
    delay_us(100);
    RF24L01_SET_CE_LOW;
}

//打开电源
void NRF24L01_PowerUp( void )
{
    NRF24L01_Write_Reg( CONFIG, NRF24L01_Read_Reg( CONFIG ) | PWR_UP );
}

//关闭电源
void NRF24L01_PowerDown( void )
{
    NRF24L01_Write_Reg( CONFIG, NRF24L01_Read_Reg( CONFIG ) & ( ~PWR_UP ));
}

// 设置模式
void NRF24L01_Set_Mode( nRf24l01ModeType Mode )
{
    uint8_t reg = 0;
    reg = NRF24L01_Read_Reg( CONFIG );
    reg = ( Mode == MODE_RX ) ? ( reg | PRIM_RX ) : ( reg & ( ~PRIM_RX ));
    NRF24L01_Write_Reg( CONFIG, reg );
}

// 设置自动重传的延时和重传次数
void NRF24L01_Set_ReTransmission( unsigned char DelayTimesOf250us, unsigned char RetransmitCount)
{
    RF24L01_SET_CS_LOW;
    NRF24L01_Write_Reg(SETUP_RETR, ( DelayTimesOf250us << 4 ) | RetransmitCount);
    RF24L01_SET_CS_HIGH;
}

// 设置发送地址
void NRF24L01_Set_TxAddr( uint8_t *pAddr, uint8_t len )
{
    len = ( len > 5 ) ? 5 : len;                  //地址不能大于5个字节
    NRF24L01_Write_Buf( TX_ADDR, pAddr, len );    //写地址
}

//  写接收通道地址
void NRF24L01_Set_RxAddr( uint8_t PipeNum, uint8_t *pAddr, uint8_t Len )
{
    Len = ( Len > 5 ) ? 5 : Len;
    PipeNum = ( PipeNum > 5 ) ? 5 : PipeNum;                    //通道不大于5 地址长度不大于5个字节
    NRF24L01_Write_Buf( RX_ADDR_P0 + PipeNum, pAddr, Len );     //写入地址
}

// 设置速度
void NRF24L01_Set_Speed( uint8_t speed )
{
    uint8_t btmp;
    btmp = NRF24L01_Read_Reg( RF_SETUP );
    btmp &= 0xD7;
    btmp |= speed;
    NRF24L01_Write_Reg( RF_SETUP, btmp );
}

// 设置功率
void NRF24L01_Set_Power( uint8_t power )
{
    uint8_t btmp;
    btmp = NRF24L01_Read_Reg( RF_SETUP );
    btmp &= 0xF9;
    btmp |= power;
    NRF24L01_Write_Reg( RF_SETUP, btmp );
}

// 设置频率频点
void RF24LL01_Set_FreqPoint( uint8_t FreqPoint )
{
    NRF24L01_Write_Reg(  RF_CH, FreqPoint & 0x7F );
}

// 清TX FIFO
void NRF24L01_Flush_Tx_Fifo ( void )
{
    NRF24L01_Write_Cmd(FLUSH_TX);
}

// 清RX FIFO
void NRF24L01_Flush_Rx_Fifo( void )
{
    NRF24L01_Write_Cmd(FLUSH_RX);
}

// 重用上一数据包
void NRF24L01_Reuse_Tx_Payload( void )
{
    RF24L01_SET_CS_LOW;
    NRF24L01_Write_Cmd(REUSE_TX_PL);
    RF24L01_SET_CS_HIGH;
}


// 读状态寄存器
uint8_t NRF24L01_Read_Status_Register( void )
{
    uint8_t Status;
    uint8_t Addr = NRF_READ_REG + STATUS;
    RF24L01_SET_CS_LOW;
    HAL_SPI_TransmitReceive(&hspi1, &Addr, &Status, 1, 0xFF);
    RF24L01_SET_CS_HIGH;
    return Status;
}

// 清中断
uint8_t NRF24L01_Clear_IRQ_Flag( uint8_t IRQ_Source )
{
    //读出寄存器中的中断标志位,并将参数中的标志位合成到读出值中
    NRF24L01_Write_Reg(STATUS, NRF24L01_Read_Status_Register( ) | (IRQ_Source & (IRQ_ALL)));
    return ( NRF24L01_Read_Status_Register( ));
}

// 读某一个或几个中断状态
uint8_t NRF24L01_Read_IRQ_Status( uint8_t IRQ_Source )
{
    return ( NRF24L01_Read_Status_Register( ) & IRQ_Source );                   //返回中断状态
}

//读取重传次数
uint8_t NRF24L01_Read_ReTransmission_Count( void )
{
    return NRF24L01_Read_Reg( OBSERVE_TX ) & 0x0F;
}

//读取丢包个数
uint8_t NRF24L01_Read_LostPackets_Count( void )
{
    return NRF24L01_Read_Reg( OBSERVE_TX ) >> 4;
}

// 读FIFO中数据宽度
uint8_t NRF24L01_Read_Top_Fifo_Width( void )
{
    uint8_t btmp;
    uint8_t tData;
    tData = R_RX_PL_WID;
    RF24L01_SET_CS_LOW;                      //片选
    HAL_SPI_Transmit(&hspi1, &tData, 1, 0xFF);
    HAL_SPI_Receive(&hspi1, &btmp, 1, 0xFF);
    RF24L01_SET_CS_HIGH;                     //取消片选
    return btmp;
}

// 写带ACK的数据到FIFO
void NRF24L01_Write_Tx_Payload_Ack( uint8_t *pTxBuf, uint8_t len )
{
    len = ( len > 32 ) ? 32 : len;           //数据长达大约32 则只发送32个
    NRF24L01_Write_Buf(WR_TX_PLOAD, pTxBuf, len);
}

// 写不带应答的数据到FIFO
void NRF24L01_Write_Tx_Payload_NoAck( uint8_t *pTxBuf, uint8_t len )
{
    len = ( len > 32 ) ? 32 : len;           //数据长达大于32 则只发送32个
    NRF24L01_Write_Buf(WR_TX_PLOAD_NACK, pTxBuf, len);
}

// 接收模式下写入附带在ACK中的数据到 ACK FIFO
void NRF24L01_Write_Tx_Payload_InAck( uint8_t *pData, uint8_t len )
{
    len = ( len > 32 ) ? 32 : len;                      //数据长度大于32个则只写32个字节
    NRF24L01_Write_Buf(W_ACK_PLOAD, pData, len);
}

// 读寄存器
uint8_t NRF24L01_Read_Reg( uint8_t RegAddr )
{
    uint8_t btmp;
    RF24L01_SET_CS_LOW;
    //将读寄存器位置1,并写入寄存器地址
    RegAddr |= NRF_READ_REG;
    HAL_SPI_Transmit(&hspi1, &RegAddr, 1, 0xFF);
    HAL_SPI_Receive(&hspi1, &btmp, 1, 0xFF);
    RF24L01_SET_CS_HIGH;
    return btmp;
}

// 读指定长度的数据

void NRF24L01_Read_Buf( uint8_t RegAddr, uint8_t *pBuf, uint8_t len )
{
    RF24L01_SET_CS_LOW;                                  //片选
    //将读寄存器位置1,并写入寄存器地址
    RegAddr |= NRF_READ_REG;
    HAL_SPI_Transmit(&hspi1, &RegAddr, 1, 0xFF);
    HAL_SPI_Receive(&hspi1, pBuf, len, 0xFF);
    RF24L01_SET_CS_HIGH;                                 //取消片选
}

// 写命令
void NRF24L01_Write_Cmd(uint8_t cmd)
{
    RF24L01_SET_CS_HIGH;
    HAL_SPI_Transmit(&hspi1, &cmd, 1, 0xFF);
    RF24L01_SET_CS_LOW;
}

// 写寄存器
void NRF24L01_Write_Reg( uint8_t RegAddr, uint8_t Value )
{
    RF24L01_SET_CS_LOW;                                  //片选
    RegAddr |= NRF_WRITE_REG;
    HAL_SPI_Transmit(&hspi1, &RegAddr, 1, 0xFF);
    HAL_SPI_Transmit(&hspi1, &Value, 1, 0xFF);
    RF24L01_SET_CS_HIGH;                                 //取消片选
}

// 写指定长度的数据
void NRF24L01_Write_Buf( uint8_t RegAddr, uint8_t *pBuf, uint8_t len )
{
    RF24L01_SET_CS_LOW;
    RegAddr |= NRF_WRITE_REG;
    HAL_SPI_Transmit(&hspi1, &RegAddr, 1, 0xFF);
    HAL_SPI_Transmit(&hspi1, pBuf, len, 0xFF);
    RF24L01_SET_CS_HIGH;
}

void NRF24L01_Init( void )
{
    uint8_t i;
    //上电等待100ms
    HAL_Delay(100);
    //禁止发送和接收,进入standby模式
    RF24L01_SET_CE_LOW;
    //关闭晶振
    NRF24L01_PowerDown();
    //清空缓存
    NRF24L01_Flush_Rx_Fifo();
    NRF24L01_Flush_Tx_Fifo();
    //写入固定的寄存器初始化数据
    for( i = 0; i < 25; i++ )
    {
        if( InitRegMap[i][0] != 0xFF )
        {
            NRF24L01_Write_Reg( InitRegMap[i][0], InitRegMap[i][1] );
        }
        else
        {
            break;
        }
    }
    //写入地址
    for( i = 0; i < 3; i++ )
    {
        NRF24L01_Write_Buf((uint8_t)InitAddr[i][0], (uint8_t*)(InitAddr[i] + 1), 5);
    }
    //开启电源
    NRF24L01_PowerUp();
    //延时,让晶振启动,进入待机模式
    HAL_Delay( 5 );
}

unsigned char NRF24L01_check( void )
{
    uint8_t i;
    uint8_t buf[5] = { 0XAA, 0X55, 0XAA, 0X55, 0XAA };
    uint8_t read_buf[ 5 ] = { 0 };
    while( 1 )
    {
        NRF24L01_Write_Buf( TX_ADDR, buf, 5 );
        NRF24L01_Read_Buf( TX_ADDR, read_buf, 5 );
        for( i = 0; i < 5; i++ )
        {
            if( buf[ i ] != read_buf[ i ] )
            {
                break;
            }
        }
        if( 5 == i )
        {
            return 1;
        }
        return 0;
    }
}


